// Copyright (C) 2022 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
//
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<广西木子科技有限公司>，授权编号：<NT220402151538>，代码指纹：<A.648883738.885>，技术对接人微信：<ID: Lingmuziyi>】
// 【授权寄送：<收件：李先生、地址：南宁市科园西十路11号国电智能大厦1101F、电话：17736659550、邮箱：yingshashou@vip.qq.com>】
//
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
//
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.eva.framework.utils;

import java.util.Vector;

import com.eva.epc.common.util.CommonUtils;
import com.eva.framework.dbpool.DBShell;

/**
 * 序列号(serial number)生成实现类.<br>
 * 获取序列号并完成对序列配置信息的数据库更新操作.<br>
 * 单号生成规则定义于数据库表esys_sn里.
 *
 * @author Jack Jiang(http://www.52im.net/space-uid-1.html)
 * @version 1.0
 */
public class SNHelper {
    /**
     * 系列号生成配置信息存放表名
     */
    private static String snConfTableName = "esys_sn";//TableConst.DEFAULT_T_SYS_SERIAL_GEN;
    /**
     * 数据库操作实用类
     */
    private static DBShell db = new DBShell();

    /**
     * 按默认值指定属性构造对象
     */
    public SNHelper() {
        this(snConfTableName);
    }

    /**
     * 按指定属性构造对象
     *
     * @param tableName 序列号配置信息数据库表名
     */
    public SNHelper(String tableName) {
        setSNConfTableName(tableName);
        db = new DBShell();
    }

    /**
     * 按数据库配置中的序列名获取序列号，支持一次获取多个序列号（是连续的）.
     *
     * @param snName 存放序列号配置表中的要取的序列名
     * @param count  要取的个数（一般情况下会是1，支持多个序列号一次生成，1～N）
     * @return 返回生成的序列号数组，数组长度=count
     */
    public static synchronized String[] getMultiSN(String snName, int count) {
        //最后的编号
        String[] sequence = new String[count];
        //编号当前值
        long currentValue = -1;
        //最小值
        long minValue = -1;
        //最大值
        long maxValue = -1;
        //编号位数
        int digit = -1;
        //编号规则
        String appendStr = "";

        //构造查询语句
        StringBuffer sql = new StringBuffer().append(
                "select " + ESYS_SN.current_val + "," + ESYS_SN.min_val + ","
                        + ESYS_SN.max_val + "," + ESYS_SN.digit + "," + ESYS_SN.head_str + " from ")
                .append(snConfTableName)
                .append(" where " + ESYS_SN.sn_name + " = '")
                .append(snName)
                .append("'");
        try {
            //获取当前序列号值，最小值，最大值，位数
            Vector returnValue = db.queryData(sql.toString());
            returnValue = (Vector) returnValue.elementAt(0);
            currentValue = Long.parseLong(returnValue.elementAt(0).toString());
            minValue = Long.parseLong(returnValue.elementAt(1).toString());
            maxValue = Long.parseLong(returnValue.elementAt(2).toString());
            digit = Integer.parseInt(returnValue.elementAt(3).toString());
            appendStr = returnValue.elementAt(4).toString();

            //不合理（当前生成的序列号超过了配置时定的最大值 和最小值边界了）
            if ((currentValue + count) > maxValue || currentValue < minValue) {
                StringBuilder sb = new StringBuilder();
                sb.append("生成的序列号越界了，(")
                        .append(currentValue).append("+").append(count).append(")>")
                        .append(maxValue).append(" || ").append(currentValue).append("<")
                        .append(minValue).append(",snName=").append(snName).append(" count=").append(count);
                LoggerFactory.getLog().warn(sb.toString());
            }
            //合理，更新当前值
            else {
                //currentValue++;
                currentValue += count;
                sql = new StringBuffer()
                        .append("update ").append(snConfTableName)
                        .append(" set " + ESYS_SN.current_val + "=?")
                        .append(" where " + ESYS_SN.sn_name + "=?");
                try {
                    db.update(sql.toString(), new Object[]{currentValue, snName}, true);
                    sequence = CommonUtils.sequence(currentValue - count, count, digit, appendStr);
                } catch (Exception e) {
                    LoggerFactory.getLog().warn("执行SQL=" + sql + "时出错," + e.getMessage());
                }
            }
        } catch (Exception ex) {
            LoggerFactory.getLog().warn(ex.getMessage(), ex);
        }
        return sequence;
    }

    /**
     * 按数据库配置中的序列名获取序列号，一次获取一个序列号.
     *
     * @param numberName 据库配置中的序列名
     * @return 得到的序列号，如为""则表示出错了
     */
    public static synchronized String getSN(String numberName) {
        String[] seq = getMultiSN(numberName, 1);
        if (seq[0] == null) {
            seq[0] = "";
            LoggerFactory.getLog().warn("获取一个序列号失败,numberName=" + numberName);
        }
        return seq[0];
    }

    public static String getSNConfTableName() {
        return snConfTableName;
    }

    public static void setSNConfTableName(String snConfTableName) {
        SNHelper.snConfTableName = snConfTableName;
    }

    // 数据库表esys_sn表字段定义（与数据库中的表字段严格对应，请保持一致！）
    public interface ESYS_SN {
        String sn_name = "sn_name";
        String current_val = "current_val";
        String min_val = "min_val";
        String max_val = "max_val";
        String digit = "digit";
        String head_str = "head_str";
        String bz = "bz";
        String gen_time = "gen_time";
    }
}
